#ifndef TASKQUEUE_HPP
#define TASKQUEUE_HPP

#include <functional>
#include <iostream>
#include <mutex>
#include <queue>
using namespace std;

// 任务
typedef function<void(void *)> callback;
template <class T>
class Task
{
public:
    Task()
    {
        function = nullptr;
        arg      = nullptr;
    }

    Task(callback f, void *arg)
    {
        function  = f;
        this->arg = (T *)arg;
    }

    callback function;
    T *arg;
};

// 任务队列
template <class T>
class TaskQueue
{
public:
    TaskQueue(){};
    ~TaskQueue(){};
    void addTask(const Task<T> &task);
    Task<T> takeTask();

    inline unsigned int taskNumber() { return taskQueue.size(); }

private:
    queue<Task<T>> taskQueue; // 任务队列
    mutex mtx;                // 互斥锁
};

// 添加任务
template <class T>
void TaskQueue<T>::addTask(const Task<T> &task)
{
    lock_guard<mutex> lock(mtx); // 互斥锁，自动释放
    taskQueue.push(task);
}

// 从队列取出一个任务
template <class T>
Task<T> TaskQueue<T>::takeTask()
{
    lock_guard<mutex> lock(mtx); // 互斥锁，自动释放
    Task<T> task;
    if (!taskQueue.empty())
    {
        task = taskQueue.front();
        taskQueue.pop();
    }
    return task;
}

#endif